package com.example.demo.utils;

import com.example.demo.ResponseEntity;
import com.sun.org.apache.bcel.internal.generic.FLOAD;
import fr.opensagres.poi.xwpf.converter.core.ImageManager;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * Created by xiaoshuai on 2019/6/12.
 */
public class FtpFileUtil {

    //ftp服务器ip地址
    private static final String FTP_ADDRESS = "192.168.25.132";
    //端口号
    private static final int FTP_PORT = 21;
    //用户名
    private static final String FTP_USERNAME = "yue";
    //密码
    private static final String FTP_PASSWORD = "root";
    //文件存储路径
    public static final String FOLDER = "/home/yue/data/";
    //切换目录
    private static final String FTP_BASEPATH = "data";

//    private static FTPClient ftp;

    private static Logger logger = LoggerFactory.getLogger(FtpFileUtil.class);

    // 空的office文档返回预览的html内容
    public static final String EMPTY_WORD_HTML = "<html><head></body></html>";

    public static FTPClient init() {
        FTPClient ftp = new FTPClient();
        ftp.setControlEncoding("UTF-8");
        ftp.enterLocalPassiveMode();
        try {
            int reply;
            ftp.connect(FTP_ADDRESS, FTP_PORT);// 连接FTP服务器
            ftp.login(FTP_USERNAME, FTP_PASSWORD);// 登录 默认进入用户的根目录，即/home/yue/
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                throw new RuntimeException("ftp服务器连接失败");
            }
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
//            ftp.makeDirectory(FTP_BASEPATH);//在用户根目录在创建一级目录
            ftp.changeWorkingDirectory(FTP_BASEPATH);
            return ftp;
        } catch (Exception e) {
            logger.info("ftp服务器连接失败！");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 上传文件
     *
     * @param file 上传的文件
     * @return
     */
    public static ResponseEntity uploadFile(MultipartFile file) {
        ResponseEntity responseEntity = new ResponseEntity();
        FTPClient ftp = init();
        if (ftp == null) {
            logger.info("ftp服务器连接失败！");
            responseEntity.setCode(500);
            responseEntity.setMsg("ftp服务器连接失败！");
            return responseEntity;
        }
        try {
            if (file == null || file.getSize() == 0) return null;
            String fileName = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            if (fileName.lastIndexOf(".") != -1) {
                String substring = fileName.substring(fileName.lastIndexOf("."));
                fileName = UUID.randomUUID().toString().toLowerCase().replace("-", "") + substring;
            } else {
                fileName = UUID.randomUUID().toString().toLowerCase().replace("-", "");
            }
            boolean storeFile = ftp.storeFile(fileName, inputStream);
            inputStream.close();
            if (storeFile) {
                responseEntity.setCode(200);
                responseEntity.setData(fileName);
                logger.info("上传成功....");
            } else {
                logger.info("上传失败....");
                responseEntity.setCode(500);
                responseEntity.setMsg("未知错误");
            }
        } catch (IOException e) {
            logger.info("上传失败....");
            e.printStackTrace();
            responseEntity.setCode(500);
            responseEntity.setMsg(e.getMessage());
        }
        return responseEntity;
    }

    /**
     * @param pathUrl  要下载的文件路径
     * @param response 响应体
     * @param fileName 文件名，如不传，默认文件名称为“附件”
     */
    public static void downloadFile(String pathUrl, HttpServletResponse response, String fileName) {
        FTPClient ftp = init();
        if (ftp == null) {
            throw new RuntimeException("ftp服务器连接失败!");
        }
        try {
            InputStream inputStream = ftp.retrieveFileStream(pathUrl);
            if (inputStream == null) {
                return;
            }
            response.setContentType("application/octet-stream");
            int i = pathUrl.lastIndexOf(".");
            String substring = "";
            if (i >= 0) {
                substring = pathUrl.substring(i);
            }
            fileName = StringUtils.isBlank(fileName) ? "附件" : fileName;
            fileName = new String(fileName.getBytes("gbk"), "iso8859-1");
            response.setHeader("Content-disposition", String.format("attachment; filename=" + fileName + substring));
            IOUtils.copy(inputStream, response.getOutputStream());
            inputStream.close();//必须
            ftp.completePendingCommand();//必须，不然后续命令会报错
            logger.info("下载成功....");
        } catch (IOException e) {
            logger.info("下载失败....");
            e.printStackTrace();
        }
    }

    /**
     * 删除文件
     *
     * @param pathUrl 文件路径
     * @return
     */
    public static ResponseEntity deleteFile(String pathUrl) {
        ResponseEntity entity = new ResponseEntity();
        FTPClient ftp = init();
        if (ftp == null) {
            logger.info("ftp服务器连接失败！");
            entity.setCode(500);
            entity.setMsg("ftp服务器连接失败！");
            return entity;
        }
        InputStream inputStream = null;
        try {
            inputStream = ftp.retrieveFileStream(pathUrl);
            if (inputStream == null) {
                entity.setCode(404);
                entity.setData(false);
                entity.setMsg("路径" + pathUrl + "不存在");
                logger.info("路径" + pathUrl + "不存在");
                return entity;
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //放在主线程里，当删除office及pdf文档时，一直在转圈，放在线程里面，解决此问题
                        ftp.deleteFile(pathUrl);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            entity.setCode(200);
            entity.setData(true);
            logger.info("删除成功....");
        } catch (IOException e) {
            logger.info("删除失败....");
            e.printStackTrace();
            entity.setData(false);
            entity.setCode(500);
            entity.setMsg(e.getMessage());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();//必须
                }
                ftp.completePendingCommand();//必须，不然后续命令会报错
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return entity;
    }

    /**
     * 预览图片，文本文件及pdf
     *
     * @param response 文件路径
     * @param pathUrl
     */
    public static void previewImage(HttpServletResponse response, String pathUrl) {
        FTPClient ftp = init();
        if (ftp == null) {
            throw new RuntimeException("ftp服务器连接失败!");
        }
        InputStream inputStream = null;
        try {
            inputStream = ftp.retrieveFileStream(pathUrl);
            if (inputStream == null) {
                return;
            }
//            response.setCharacterEncoding("UTF-8");加上这句会乱码，奇了怪了
            Path path = Paths.get(pathUrl);
            String contentType = Files.probeContentType(path);
            response.setContentType(contentType);
            IOUtils.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();//必须
                }
                ftp.completePendingCommand();//必须，不然后续命令会报错
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 预览word文档，兼容2003,2007
     *
     * @param pathUrl 文件路径
     * @return
     */
    public static String previewWord(String pathUrl) {
        FTPClient ftp = init();
        if (ftp == null) {
            throw new RuntimeException("ftp服务器连接失败!");
        }
        InputStream inputStream = null;
        try {
            inputStream = ftp.retrieveFileStream(pathUrl);
            if (inputStream == null) {
                return EMPTY_WORD_HTML;
            }
            return word7ToHtml(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();//必须
                }
                ftp.completePendingCommand();//必须，不然后续命令会报错
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 预览excel文档，兼容2003,2007
     *
     * @param pathUrl 文件路径
     * @return
     */
    public static String previewExcel(String pathUrl) {
        FTPClient ftp = init();
        if (ftp == null) {
            throw new RuntimeException("ftp服务器连接失败!");
        }
        InputStream inputStream = null;
        try {
            inputStream = ftp.retrieveFileStream(pathUrl);
            if (inputStream == null) {
                return EMPTY_WORD_HTML;
            }
            return POIReadExcel.excelWriteToHtml(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();//必须
                }
                ftp.completePendingCommand();//必须，不然后续命令会报错
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    /**
     * 将word2007转换成html
     *
     * @param
     */
    public static String word7ToHtml(InputStream inputStream) {
        URL resource = FtpFileUtil.class.getClassLoader().getResource("");
        File file = new File(resource.getPath() + System.getProperty("file.separator") + "static");
        if (!file.exists()) {
            boolean mkdir = file.mkdirs();
            System.out.println(mkdir);
        }
        XWPFDocument document = open(inputStream);
        if (document == null) {
            return null;
        }
//        String path = System.getProperty("user.dir") + System.getProperty("file.separator");
        XHTMLOptions options = XHTMLOptions.create();
        options.setImageManager(new ImageManager(file, "image"));
        OutputStream out = new ByteArrayOutputStream();
        try {
            XHTMLConverter.getInstance().convert(document, out, options);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toString();
    }

    /**
     * 打开一个word2007文档
     *
     * @param
     * @return
     */
    public static XWPFDocument open(InputStream inputStream) {
        XWPFDocument document = null;
        try {
            document = new XWPFDocument(new BufferedInputStream(inputStream));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return document;
    }
}